package com.ruike.alisurface.Serials;

import com.ruike.alisurface.Constant;
import com.ruike.lib_serialport.callback.SerialCallBack;
import com.ruike.lib_serialport.utils.SerialPortTtys3Util;
import com.voodoo.lib_utils.ByteUtils;
import com.voodoo.lib_utils.L;
import com.voodoo.lib_utils.ShareUtils;

import org.greenrobot.eventbus.EventBus;

import static com.ruike.alisurface.utils.ShareKey.Type_Chshopzl;
import static com.ruike.alisurface.utils.ShareKey.Type_Chshopzl_OLD;
import static com.ruike.alisurface.utils.ShareKey.Type_Chshopzl_SIXOLD;
import static com.ruike.alisurface.utils.ShareKey.Type_Lockclose;
import static com.ruike.alisurface.utils.ShareKey.Type_Lockopen;
import static com.ruike.alisurface.utils.ShareKey.Type_Steal;
import static com.ruike.alisurface.utils.ShareKey.Type_sendPlankVersion;
import static com.ruike.alisurface.utils.ShareKey.Type_toGoshopzl;

/**
 * 串口3 的底层通信类
 */
public class Ttys3Utils implements SerialCallBack {


    private static Ttys3Utils ttys3Utils;

    public static Ttys3Utils getInstance() {
        if (ttys3Utils == null) {
            synchronized (Ttys3Utils.class) {
                if (ttys3Utils == null) {
                    ttys3Utils = new Ttys3Utils();
                }
            }
        }
        return ttys3Utils;
    }

    public void OpenPort() {
        SerialPortTtys3Util.open();
        L.i("打开串口3");
    }

    public void SendPort(String strmsg) {
        SerialPortTtys3Util.sendHex(strmsg);
//        L.i("串口3： 发送指令：" + strmsg);
    }

    /**
     * @Params: 一个串口数据回调接口
     */
    public interface Serial3CallBack {
        void onSerialPortData(String type, String serialPortData);
    }

    public void setSerial3CallBack(Serial3CallBack serial3CallBack) {
        this.serial3CallBack = serial3CallBack;
    }

    public Serial3CallBack serial3CallBack;

    @Override
    public void onSerialPortOpenListener(boolean isOpenSuccess, String portName, String msg) {
        // 串口打开结果回调
    }

    @Override
    public void onSerialPortData(String serialPortData, byte[] resultBytes) {
        L.i("串口3： 返回值：" + serialPortData);
        if (serialPortData.isEmpty()) {
            L.i("串口3： 返回值：数据异常");
            return;
        }
        if (serialPortData.length() <= 2) {
            return;
        }
        String[] data_code = serialPortData.split(" ");
        String data = serialPortData.replaceAll(" ", "");

        getWkVersion(data);
        getPlankzVersion(data);
        getJudgeiswk(serialPortData);
        if (data.equals("10020618")) {
            L.i("onMessageEvent： " + "发送数据");
            EventBus.getDefault().post(new MsgEventBus(Type_toGoshopzl, serialPortData));
            return;
        }
        // 10 0E 02 04 01 00 00 01 13 0B 1D 13 0C 05 1A 9F
        if (data_code[1].equals("0E") && data_code[2].equals("02")) {
            L.i("IC2 串口3  出货完成指令===" + serialPortData);
            EventBus.getDefault().post(new MsgEventBus(Type_Chshopzl, serialPortData));
            return;
        }
        // 10 07 02 02 01 1A 00 01 37
        if (data_code[1].equals("07") && data_code[2].equals("02")) {
            EventBus.getDefault().post(new MsgEventBus(Type_Chshopzl_OLD, serialPortData));
        }
        // 10 06 02 01 2F 00 00 48
        if (data_code[1].equals("06") && data_code[2].equals("02")) {
            EventBus.getDefault().post(new MsgEventBus(Type_Chshopzl_SIXOLD, serialPortData));
        }
        if (data_code[1].equals("08") && data_code[2].equals("04")) {
            if (resultBytes[3] == (byte) 0x01) {
                L.i("收到开锁指令===" + serialPortData);
                return;
            }
            L.i("IC2 串口3  电控锁开门指令===" + serialPortData);
            EventBus.getDefault().post(new MsgEventBus(Type_Lockopen, serialPortData));
            return;
        }
        if (data_code[1].equals("06") && data_code[2].equals("1F")) {
            L.i("IC2 串口3  电控锁关门指令===" + serialPortData);
            EventBus.getDefault().post(new MsgEventBus(Type_Lockclose, serialPortData));
            return;
        }
        if (data_code[1].equals("05") && data_code[2].equals("1E")) {
            L.i("IC2 串口3  偷盗指令===" + serialPortData);
            EventBus.getDefault().post(new MsgEventBus(Type_Steal, serialPortData));
        }
    }

    /**
     * 新驱动板对接
     * 二．数据协议格式
     * 数据格式：驱动板地址+数据长度+命令数据+总出货货道数量+1货道号+1出货数量+1货道类型+2货道号+2货道出货数量+2货道类型
     * +3货道号+3货道出货数量+3货道类型+4货道号+4货道出货数量+4货道类型+5货道号+5货道出货数量+5货道类型+前面数据和低八位。
     * 注：
     * （1）驱动板地址为485通讯地址，驱动板从10（0x0AH）开始，驱动板1为0x0A，驱动板2为0x0B，以此类推。
     * （2）数据长度为第一位与此数据长度位之外的数据长度。
     * （3）命令数据表示该指令的控制对象。
     * （4）总出货数量为一次性选择的出货货道总数，最大值为5，也就是说一次性最多可以买五种商品。1表示一次出一种货，此时数据格式：
     * 驱动板地址+数据长度+命令数据+总出货货道数量+1货道号+1货道类型+前面数据和低八位。
     * （5）货道号为货物所在货道编码。
     * （6）货道类型：0-弹簧货道，1-电磁锁货道，2-履带
     * <p/>
     * <p/>
     * typelength: 长度   index：货道  index：货道类型
     * <p>
     * 10 06 00 01 2E 01 00 46
     */
    public void Qudong(int typelength, int index, String indexType) {
        SendPort(SerialPortInstructUtils.quDongOutGoods(index, Integer.valueOf(indexType)));

    }


    /**
     * LED灯光设置
     * A.操作LED指令  pcbaddress 电路板地址
     * 数据格式：升降机电路板地址+数据长度+操作命令数据+LED灯工作模式+LED通道号+
     * 对应通道号LED开关状态（只在开关模式下有效）+LED灯最大亮度（只在呼吸模式下有效，0-30）
     * +呼吸灯呼吸时间（只在呼吸模式下有效，0-30）+LED使能状态+前面数据和低八位。
     * <p/>
     * （1）升降机电路板地址为485通讯地址
     * （2）数据长度为除第一位与此数据长度位之外的数据长度
     * （3）操作命令数据表示该指令的控制对象。
     * （4）LED工作模式：0-开关，1-呼吸
     * （（5）LED通道号：0为LED1，1为LED2
     * （6）对应通道号LED开关状态（只在开关模式下有效）：0-关，1-开
     * （7）呼吸灯最大亮度（只在呼吸模式下有效）：取值1-30
     * （8）呼吸灯呼吸时间（只在呼吸模式下有效）：取值1-30
     * （9）LED使能状态：0-失能，1-使能
     * （10）校验位：前面数据和低八位
     */
    public void LEDSetting(int pcbaddress, String ledmode, String chanl, String state, int largLight, int largtime) {
        SendPort(SerialPortInstructUtils.quDongLed(pcbaddress, Integer.valueOf(ledmode), Integer.valueOf(chanl), (Integer.valueOf(state) == 1), largLight, largtime));
    }

    /**
     * 发送温控信息指令
     *
     * @param box_no    主副柜  0 主  1 2 3
     * @param resultStr 要执行的字符串
     */
    public void sendTemperatureControl(int box_no, String resultStr) {
        byte[] resultBytes = ByteUtils.hexToByteArr(resultStr); // 直接转换成byte数组
        byte box_nos = (byte) (0x23 + box_no);
        SendPort(SerialPortInstructUtils.temperatureControl(box_nos, resultBytes));
    }


    /**
     * 门电控锁
     * ElecEn：电磁锁使能标志，0-关闭此功能，1-开启此功能，在0的状态下，所有设置无效。
     * ElecNum：需要打开哪个电磁锁，0表示1通道，1表示2通道
     * ElecOnTi：电磁锁通电时间，取值3-50，对应0.3s-5s
     * ElecState：对应通道电磁锁的状态，0表示没有通电，1表示已通电。
     * boxno:货柜编号 0是主柜 其余递推
     *
     * @param boxno
     */
    public void DoorSetting(int boxno, int ElecOnTi, int ElecNum) {
        SendPort(SerialPortInstructUtils.quDongOpenElectricDoor(boxno, ElecOnTi, ElecNum));
    }


    /**
     * 查询驱动程序版本号和驱动板批次
     *
     * @param zfg 主副柜
     */
    public void sendCheckVersion(int zfg) {

        SendPort(SerialPortInstructUtils.quDongCheckVersion(zfg));
    }

    /**
     * 查询温控程序版本号和驱动板批次
     * 23 03 03 06 2F
     * 23 03 03 03 2C
     *
     * @param zfg
     */
    public void sendCheckWKVersion(int zfg) {

        SendPort(SerialPortInstructUtils.quDonfCheckWKVersion(zfg));
    }


    /**
     * 得到板子信息
     *
     * @param data
     */
    public void getPlankzVersion(String data) {
        if (data.length() < 6) {
            L.i("查询程序版本号和驱动板批次  长度不够");
            return;
        }
        String[] str = new String[]{"MV", "Fir", "Sec", "Thi"};
        //判断是否是主柜或者副柜几
        String zfg = null;
        if (data.substring(0, 2).equals("10")) {
            zfg = str[0];
        } else if (data.substring(0, 2).equals("11")) {
            zfg = str[1];
        } else if (data.substring(0, 2).equals("12")) {
            zfg = str[2];
        } else if (data.substring(0, 2).equals("13")) {
            zfg = str[3];
        }
        if (data.substring(4, 6).equals("1D")) {
            if (data.length() < 20) {
                L.i("查询程序版本号和驱动板批次  长度不够");
                return;
            }
            int length = Integer.parseInt(data.substring(2, 4), 16);
            L.i("查询程序长度  length =" + length);
            String PlankzVersion;
            if (length > 9) {
                PlankzVersion = data.substring(8, 22);
            } else {
                PlankzVersion = data.substring(8, 20);
            }
            L.i("查询程序版本号和驱动板批次" + PlankzVersion);
            EventBus.getDefault().post(new MsgEventBus(Type_sendPlankVersion, zfg + "-" + PlankzVersion));
        }
        return;
    }


    /**
     * 得到温控信息
     *
     * @param data
     */
    public void getWkVersion(String data) {
        if (data.length() < 6) {
            L.i("查询温控程序版本号和驱动板批次 T-长度不够");
            return;
        }
        if (data.substring(0, 2).equals("23")) {
            if (data.substring(4, 6).equals("06")) {
                if (data.length() < 18) {
                    L.i("查询温控程序版本号和驱动板批次 T-长度不够");
                    return;
                }
                String WKVersion = data.substring(6, 18);
                L.i("查询温控程序版本号和驱动板批次 T-" + WKVersion);
                ShareUtils.getInstance().putString("T", WKVersion);
            }
        }
        return;
    }

    /**
     * 解析温控度
     *
     * @param date
     */
    public void getJudgeiswk(String date) {

        String[] temp = date.split(" ");
        String head = temp[0];
        if (head.equals("23")) {
            EventBus.getDefault().post(new MsgEventBus("温控返回", date));
            L.i("温控值=" + date);
            String type = temp[2];
            L.i("type=" + type);
            if (type.equals("01")) { //温湿度
                if (serial3CallBack != null) {
                    serial3CallBack.onSerialPortData("01", date);
                }
            } else if (type.equals("02")) {//继电器
                if (serial3CallBack != null) {
                    serial3CallBack.onSerialPortData("02", date);
                }
            } else if (type.equals("03")) {//运行类型
                if (serial3CallBack != null) {
                    serial3CallBack.onSerialPortData("03", date);
                }
            }
        }
        return;
    }


    // =============================================================================================
    // ======    串口回调接口二次封装，便于在utils中回调读取和使用并且在此类中进行公共的操作处理
    // =============================================================================================

    public OnSerialPortResultDataListener onSerialPortResultDataListener;

    public void setOnSerialPortResultDataListener(OnSerialPortResultDataListener onSerialPortResultDataListener) {
        this.onSerialPortResultDataListener = onSerialPortResultDataListener;
    }

    /**
     * 串口数据回调接口
     */
    public interface OnSerialPortResultDataListener {
        /**
         * 串口回调
         *
         * @param serialPortData 字符串格式回调
         * @param resultBytes    byte数值格式回调
         */
        void serialPortResultData(String serialPortData, byte[] resultBytes);
    }

}
